package com.qianniu.napi.common.util;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.qianniu.napi.common.config.Constants;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyStore;
import java.util.List;
import java.util.Map;

public class HttpUtil {

    private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);

    public static void main(String[] args) {
        //发送 GET 请求
//        String s=HttpUtil.sendGet("http://v.qq.com/x/cover/kvehb7okfxqstmc.html?vid=e01957zem6o", "");
//        System.out.println(s);

//        //发送 POST 请求
//        String sr=HttpUtil.sendPost("http://www.toutiao.com/stream/widget/local_weather/data/?city=%E4%B8%8A%E6%B5%B7", "");
//        JSONObject json = JSONObject.fromObject(sr);
//        System.out.println(json.get("data"));
    }

    public static String sendGet(String url, String param) {
        return sendGet(url, param, null);
    }

    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url   发送请求的URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param, String encoding) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = Strings.isNullOrEmpty(param) ? url : url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = Strings.isNullOrEmpty(encoding) ? new BufferedReader(new InputStreamReader(connection.getInputStream())) :
                    new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }

        } catch (Exception e) {
            System.out.println("发送GET请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        logger.debug("======sendGet=" + result);
        return result;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        System.out.println(">>>result" + result);
        return result;
    }

    private final static int CONNECT_TIMEOUT = 5000; // in milliseconds
    private final static String DEFAULT_ENCODING = "UTF-8";

    public static String postData(String urlStr, String data) {
        return postData(urlStr, data, null);
    }

    public static String postData(String urlStr, String data, String contentType) {
        BufferedReader reader = null;
        try {
            URL url = new URL(urlStr);
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            conn.setConnectTimeout(CONNECT_TIMEOUT);
            conn.setReadTimeout(CONNECT_TIMEOUT);
            if (contentType != null)
                conn.setRequestProperty("content-type", contentType);
            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
            if (data == null)
                data = "";
            writer.write(data);
            writer.flush();
            writer.close();

            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
                sb.append("\r\n");
            }
            return sb.toString();
        } catch (IOException e) {
            //logger.error("Error connecting to " + urlStr + ": " + e.getMessage());
        } finally {
            try {
                if (reader != null)
                    reader.close();
            } catch (IOException e) {
            }
        }
        return null;
    }

    public static boolean downloadFile(String imaurl, String targetFile) {
        // 下载网络文件
        int bytesum = 0;
        int byteread = 0;
        boolean result = true;

        try {
            logger.debug(">>>>>> downloadFile start and imaurl=" + imaurl);
            URL url = new URL(imaurl);
            File file = new File(targetFile);
            if (file.exists()) {
                file.delete();
                file = new File(targetFile);
            }

            checkDirectory(targetFile);

            URLConnection conn = url.openConnection();
            InputStream inStream = conn.getInputStream();
            FileOutputStream fs = new FileOutputStream(targetFile);

            byte[] buffer = new byte[1204];
            while ((byteread = inStream.read(buffer)) != -1) {
                bytesum += byteread;
                fs.write(buffer, 0, byteread);
            }
            logger.debug(">>>>>> downloadFile OK and targetFile=" + targetFile);
        } catch (FileNotFoundException e) {
            logger.error("FileNotFoundException", e);
            result = false;
        } catch (IOException e) {
            logger.error("IOException", e);
            result = false;
        }
        return result;
    }

    // 检查路径的所有目录是否创建
    public static void checkDirectory(String path) {
        logger.info("=====checkDirectory path=" + path);

        if (Strings.isNullOrEmpty(path)) return;

        int uploadsIndex = path.indexOf("/fafa/www/");
        String headpath = path.substring(0, uploadsIndex);
        String leftpath = path.substring(uploadsIndex);

        String[] arr = leftpath.split("/");

        String targetpath = headpath;
        for (int i = 0; i < arr.length; i++) {
            if (i == arr.length - 1 && arr[i].indexOf(".") >= 0) continue;
            targetpath = targetpath + arr[i] + "/";
            logger.info("=====checkDirectory targetpath=" + targetpath);
            createDir(targetpath);
        }
    }

    // 检查路径的所有目录是否创建
    public static Boolean checkFile(String path) {
        logger.info("=====checkFile path=" + path);
        File file = new File(path);
        return file.exists();
    }

    // 创建目录
    public static boolean createDir(String destDirName) {
        File dir = new File(destDirName);
        if (dir.exists()) {// 判断目录是否存在
            return false;
        }
        if (!destDirName.endsWith(File.separator)) {// 结尾是否以"/"结束
            destDirName = destDirName + File.separator;
        }
        if (dir.mkdirs()) {// 创建目标目录
            return true;
        } else {
            return false;
        }
    }

    public static String getminiQr(String accessToken, String path, String page, String scene, int width,
                                   boolean withQueryParam, String color, Boolean touming) {

        if (checkFile(path) && PictureUtil.checkimg(path))
            return path.replace("/fafa/www/images/", Constants.IMG_UPLOAD_HOST);
        try {
            logger.info("========getminiQr qrfile not exist");
            String ul = withQueryParam ? Constants.WX_URL_GETWXACODE_WITHPARAM : Constants.WX_URL_GETWXACODE;

            ul = ul.replace("ACCESS_TOKEN", accessToken);
            URL url = new URL(ul);
            logger.info("========getminiQr url=" + ul);
            URLConnection conn = url.openConnection();
//            conn.setRequestMethod("POST");// 提交模式
            // conn.setConnectTimeout(10000);//连接超时 单位毫秒
            // conn.setReadTimeout(2000);//读取超时 单位毫秒
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            PrintWriter printWriter = new PrintWriter(conn.getOutputStream());

            // 发送请求参数
            JSONObject paramJson = new JSONObject();
            if (!withQueryParam) {
                logger.info("========getminiQr scene=" + scene);
                logger.info("========getminiQr page=" + page);
                paramJson.put("scene", scene);
                paramJson.put("page", page);
            } else {
                logger.info("========getminiQr path=" + page);
                paramJson.put("path", page);
            }
            paramJson.put("width", width);
            paramJson.put("is_hyaline", touming);
            if (Strings.isNullOrEmpty(color))
                paramJson.put("auto_color", true);
            else {
                RGB rgb = ColorUtil.toRGB(color);
                paramJson.put("line_color", rgb);
            }

            logger.info("========getminiQr paramJson=" + paramJson);

            printWriter.write(paramJson.toString());
            // flush输出流的缓冲
            printWriter.flush();
            //开始获取数据
            BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
            OutputStream os = new FileOutputStream(new File(path));
            int len;
            byte[] arr = new byte[1024];
            while ((len = bis.read(arr)) != -1) {
                os.write(arr, 0, len);
                os.flush();
            }
            os.close();
            path = path.replace("/fafa/www/images/", Constants.IMG_UPLOAD_HOST);
        } catch (Exception e) {
            logger.error("====getminiQr error", e);
            path = "";
        }
        return path;
    }

    /**
     * 申请退款
     */
    public static String refundPost(String url, String data, String path, String mcid) throws Exception {

        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        FileInputStream is = new FileInputStream(new File(path));
        try {
            keyStore.load(is, mcid.toCharArray());
        } finally {
            logger.debug(">>>keyStore.load over");
            is.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mcid.toCharArray()).build();

        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

        try {
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);

            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }
}